package com.dhemery.mack.gui;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.part.ViewPart;

import com.dhemery.mack.actions.ActionList;
import com.dhemery.mack.actions.ActionSet;
import com.dhemery.mack.actions.AddFolderAction;
import com.dhemery.mack.actions.AddPageAction;
import com.dhemery.mack.actions.MenuFactory;
import com.dhemery.mack.actions.OpenAction;
import com.dhemery.mack.adapters.EditorLauncher;
import com.dhemery.mack.adapters.ImageDescriptorSource;
import com.dhemery.mack.adapters.NodeAdapterFactory;
import com.dhemery.mack.application.MackPlugin;

//TODO Test this class
public class ProjectExplorer extends ViewPart {
	public static final String ID = "com.dhemery.mack.view.ProjectExplorer";
	private DoubleClickHandler doubleClickResponder;
	private NodeChangeHandler nodeChangeResponder;
	private TreeViewer viewer;

	private ActionSet createActions() {
		IAdapterFactory adapterFactory = MackPlugin.getInstance().getAdapterFactory();
		ImageDescriptorSource imageDescriptorSource = MackPlugin.getInstance();

		ActionSet actionSet = new ActionSet();
		
		actionSet.add(createEditActions(adapterFactory, imageDescriptorSource));
		actionSet.add(createAddActions(adapterFactory, imageDescriptorSource));
		
		return actionSet;
	}

	private ActionList createAddActions(IAdapterFactory adapterFactory, ImageDescriptorSource imageDescriptorSource) {
		ActionList actionList = new ActionList("Add");
		actionList.add(new AddFolderAction(getPage(), viewer, adapterFactory, imageDescriptorSource));
		actionList.add(new AddPageAction(getPage(), viewer, adapterFactory, imageDescriptorSource));
		return actionList;
	}

	private IContributionManager createContextMenu() {
		MenuManager menuManager = new MenuManager();
		menuManager.setRemoveAllWhenShown(false);
		Menu menu = menuManager.createContextMenu(viewer.getTree());
		getSite().registerContextMenu(menuManager, viewer);
		viewer.getTree().setMenu(menu);
		return menuManager;
	}

	private ActionList createEditActions(IAdapterFactory adapterFactory, ImageDescriptorSource imageDescriptorSource) {
		ActionList actionList = new ActionList("Edit");
		actionList.add(new OpenAction(getPage(), viewer, adapterFactory, imageDescriptorSource));
		return actionList;
	}

	private void createMenus() {
		new MenuFactory().fillMenus(createMenuManagers(), createActions());
	}

	private List<IContributionManager> createMenuManagers() {
		List<IContributionManager> menus = new ArrayList<IContributionManager>();
		menus.add(createViewMenu());
		menus.add(createToolBar());
		menus.add(createContextMenu());
		return menus;
	}

	@Override
	public void createPartControl(Composite parent)
	{
		createTreeViewer(parent);
		createMenus();
		subscribeToEvents();
		startPublishingSelections();
	}

	private IContributionManager createToolBar() {
		return getViewSite().getActionBars().getToolBarManager();
	}

	private void createTreeViewer(Composite parent) {
		viewer = new TreeViewer(parent, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL);
		viewer.setContentProvider(new BaseWorkbenchContentProvider());
		viewer.setLabelProvider(new WorkbenchLabelProvider());
		viewer.setInput(getDefaultInput());
		viewer.expandAll();
	}

	private IContributionManager createViewMenu() {
		return getViewSite().getActionBars().getMenuManager();
	}

	private EditorLauncher createWindowEditorLauncher() {
		return new EditorLauncher(getPage(), new NodeAdapterFactory(getImageDescriptorSource()));
	}

	@Override
	public void dispose() {
		stopPublishingSelections();
		unsubscribeFromEvents();
		super.dispose();
	}

	private IAdaptable getDefaultInput() {
		return getSite().getPage().getInput();
	}

	private ImageDescriptorSource getImageDescriptorSource() {
		return MackPlugin.getInstance();
	}

	private IWorkbenchPage getPage() {
		return getWindow().getActivePage();
	}

	private IWorkbenchWindow getWindow() {
		return getSite().getWorkbenchWindow();
	}

	public void setFocus() {
		viewer.getControl().setFocus();
	}

	private void startPublishingSelections() {
		getSite().setSelectionProvider(viewer);
	}

	private void stopPublishingSelections() {
		getSite().setSelectionProvider(null);
	}

	private void subscribeToDoubleClicks() {
		doubleClickResponder = new DoubleClickHandler(viewer, createWindowEditorLauncher());
	}

	private void subscribeToEvents() {
		subscribeToNodeChanges();
		subscribeToDoubleClicks();
	}

	private void subscribeToNodeChanges() {
		nodeChangeResponder = new NodeChangeHandler(viewer);
	}

	private void unsubscribeFromDoubleClicks() {
		doubleClickResponder.dispose();
	}

	private void unsubscribeFromEvents() {
		unsubscribeFromDoubleClicks();
		unsubscribeFromNodeChanges();
	}

	private void unsubscribeFromNodeChanges() {
		nodeChangeResponder.dispose();
	}
}
